package com.lamatek.beans.google;

import javax.servlet.ServletRequest;
import javax.servlet.jsp.PageContext;

import com.lamatek.tags.google.GoogleMapEventHandler;
import com.lamatek.tags.google.GoogleMapTag;

/**
 * DefaultEventListenerBean
 * 
 * This class is the parent class for all bean based event listeners
 * for the &lt;googlemaps> JSP Taglibrary. It provides support for all the
 * events available. When declaring &lt;googlemaps:event> tags in your
 * map, pass the URL to the page containing your subclass of DefaultEventListenerBean as
 * the url attribute. This will typically be the same page the contains
 * the map. Using this method, most Google Map applications can be written
 * using just one .jsp page and one bean.
 * 
 * Users extending this class should override the methods for the event
 * types they're interested in. It is also recommended that the user
 * first call super.processXXXEvent() for the method to ensure standard
 * map behaviour.
 * 
 * The standard process method is called after all event based centric methods
 * have been called and gives the user the opportunity to handle other non-event
 * based interactions in the same class. Using this method, it is quite possible
 * to cleanly handle the interactions for an entire application in one handler.
 * 
 * Users may also opt to use the Servlet event listening. 
 * @see com.lamatek.servlets.google.DefaultEventListenerServlet
 * 
 * @author Tom Cole
 * @version 0.40
 */
public class DefaultEventListenerBean implements GoogleMapEventHandler {

    /**
     * The pageContext that contains the request information.
     */
    private PageContext page;
    /**
     * The scope identifier for the GoogleMapTag.
     */
    private String scope = "site";
    
    /**
     * Sets the pageContext. Developers should not override this method.
     * If users override this method they <em>must</em> call super.setPageContext()
     * or else this bean will not function as expected.
     * 
     * @param page The PageContext that loads this bean.
     */
    public void setPageContext(PageContext page) {
        this.page = page;
        processRequest(page.getRequest());
    }
    /**
     * Returns the pageContext responsible for this bean.
     * 
     * @return PageContext
     */
    public PageContext getPageContext() {
        return page;
    }
    /**
     * Processes the request and forwards it to the 
     * appropriate event handler methods. Once all
     * events have been processes the requests is handed
     * to the process() method.
     * 
     * @param request The ServletRequest used to load this bean.
     */
    private void processRequest(ServletRequest request) {
        String event = request.getParameter("event");
        if (event != null) {
            String mapName = request.getParameter("map");
            if (mapName != null) {
                Object o = null;
                o = page.getSession().getAttribute(mapName);
                if (o == null) {
                    o = page.getAttribute(mapName);
                    scope = "page";
                }
                if (o != null) {
                    GoogleMapTag map = (GoogleMapTag) o;
                    if (event.equals("click")) {
                        if (request.getParameter("component") == null) {
	                        double latitude = -181.0d;
	                        double longitude = -181.0d;
	                        try {
	                            latitude = Double.parseDouble(request.getParameter("latitude"));
	                            longitude = Double.parseDouble(request.getParameter("longitude"));
	                        }
	                        catch(Exception ex) {
	                            
	                        }
	                        if ((longitude > -181.0 && latitude > -181))
	                            processClickEvent(map, longitude, latitude);
                        }
                        else {
                            processOverlayClickEvent(map, request.getParameter("component"), request.getParameter("type"));
                        }
                    }
                    else if (event.equals("dblclick")) {
                        if (request.getParameter("component") == null) {
	                        double latitude = -181.0d;
	                        double longitude = -181.0d;
	                        try {
	                            latitude = Double.parseDouble(request.getParameter("latitude"));
	                            longitude = Double.parseDouble(request.getParameter("longitude"));
	                        }
	                        catch(Exception ex) {
	                            
	                        }
	                        if ((longitude > -181.0 && latitude > -181))
	                            processDoubleClickEvent(map, longitude, latitude);
                        }
                        else {
                            processOverlayDoubleClickEvent(map, request.getParameter("component"), request.getParameter("type"));
                        }
                    }
                    else if (event.equals("zoom")) {
                        int zoom = -1;
                        try {
                            zoom = Integer.parseInt(request.getParameter("zoom"));
                        }
                        catch(Exception ex) {
                            
                        }
                        if (zoom >= 0) 
                            processZoomEvent(map, zoom);
                    }
                    else if (event.equals("moveend")) {
                        double latitude = -181.0d;
                        double longitude = -181.0d;
                        try {
                            latitude = Double.parseDouble(request.getParameter("latitude"));
                            longitude = Double.parseDouble(request.getParameter("longitude"));
                        }
                        catch(Exception ex) {
                            
                        }
                        if ((longitude > -181.0 && latitude > -181))
                            processMoveEndEvent(map, longitude, latitude);
                    }
                    else if (event.equals("maptypechanged")) {
                        String type = request.getParameter("type");
                        if (type != null)
                            processMapTypeChangedEvent(map, type);
                    }
                    process(map, page.getRequest());
                }
                else {
                    System.out.println("Unable to load map named " + mapName);
                }
            }
            else {
                System.out.println("Unable to locate target map name.");
            }
        }
        else {
            System.out.println("No event found to process.");
        }
    }
    /**
     * This method is called after all the event based methods have been called.
     * Developers can use this method to handle non-event based requests.
     * 
     * The default implementation is empty to there is no need to call
     * super.process().
     * 
     * @param map The GoogleMapTag that generated the event.
     * @param request The original ServletRequest.
     */
    public void process(GoogleMapTag map, ServletRequest request) {
        
    }
    /**
     * This method is called if a click event is detected that was generated
     * by an overlay (box, circle, marker, polygon, polyline).
     * 
     * The default implementation is empty so there is no need to call
     * super.processMarkerClickEvent().
     * 
     * @param map The GoogleMapTag parent of the marker clicked.
     * @param id The id of the overlay that was clicked.
     * @param type The type of overlay clicked (marker, box, circle, polygon, polyline)
     */
    public void processOverlayClickEvent(GoogleMapTag map, String id, String type) {
        
    }
    /**
     * This method is called when a click event is detected that was generated
     * by a GoogleMapTag (&lt;googlemaps:map>).
     * 
     * The default implementation of this method is empty so there is no need
     * to call super.processClickEvent().
     * 
     * @param map The GoogleMapTag that generated the event.
     * @param longitude The longitude (in decimal form) where the click occured.
     * @param latitude The latitude (in decimal form) where the click occured.
     */
    public void processClickEvent(GoogleMapTag map, double longitude, double latitude) {
        
    }
    /**
     * This method is called when a double-click event is detected that was
     * generated by an overlay (box, circle, marker, polygon, polyline).
     * 
     * The default implementation of this method is empty so there is no need
     * to call super.processMarkerDoubleClickEvent().
     * 
     * @param map The GoogleMapTag parent of the marker double-clicked.
     * @param id The id of the overlay double-clicked.
     * @param type The type of overlay double-clicked (marker, circle, box, polygon, polyline)
     */
    public void processOverlayDoubleClickEvent(GoogleMapTag map, String id, String type) {
        
    }
    /**
     * This method is called when a double-click event is detected that was
     * generated by a GoogleMapTag (&lt;googlemaps:map>).
     * 
     * The default implementation of this method is empty so there is no
     * need to call super.processDoubleClickEvent().
     * 
     * @param map The GoogleMapTag that generated the event.
     * @param longitude The longitude (in decimal form) where the double-click occured.
     * @param latitude The latitude (in decimal form) where the double-click occured. 
     */
    public void processDoubleClickEvent(GoogleMapTag map, double longitude, double latitude) {
        
    }
    /**
     * This method is called when a zoom event is detected.
     * 
     * The default implementation of this method simulates the default behaviour of
     * a Google Map and any subclasses should call super.processZoomEvent() to 
     * ensure consistent behaviour.
     * 
     * @param map The GoogleMapTag that generated the event.
     * @param zoom The new requested zoom level.
     */
    public void processZoomEvent(GoogleMapTag map, int zoom) {
        map.setZoom(zoom);
    }
    /**
     * This method is called when a moveend event is detected.
     * 
     * The default implementation of this method simulates the default behaviour of
     * a Google Map and any subclasses should call super.processMoveEndEvent() to 
     * ensure consistent behaviour.
     * 
     * @param map The GoogleMapTag that generated the event.
     * @param longitude The new center longitude (in decimal form).
     * @param latitude The new center latitude (in decimal form).
     */
    public void processMoveEndEvent(GoogleMapTag map, double longitude, double latitude) {
        map.setCenterLatitude(latitude);
        map.setCenterLongitude(longitude);
    }
    /**
     * This method is called when a maptypechanged event is detected.
     * 
     * The default implementation of this method simulates the default behaviour of
     * a Google Map and any subclasses should call super.processMapTypeChangedEvent() to 
     * ensure consistent behaviour.
     * 
     * @param map The GoogleMapTag that generated the event.
     * @param type The new requested map type (map | satellite | hybrid).
     */
    public void processMapTypeChangedEvent(GoogleMapTag map, String type) {
        map.setType(type);
    }
}
